package com.iisigroup.project.statistics.caliberRM;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.math.util.MathUtils;
import org.apache.lucene.util.MathUtil;
import org.robert.study.utils.Utils;

import Caliber.CaliberObjectIDHelper;
import Caliber.eObjectType;

import com.iisigroup.project.statistics.caliberRM.model.internal.CategoryEnum;
import com.starbase.caliber.Baseline;
import com.starbase.caliber.CaliberObject;
import com.starbase.caliber.CaliberObjectID;
import com.starbase.caliber.CaliberObjectManager;
import com.starbase.caliber.Project;
import com.starbase.caliber.Requirement;
import com.starbase.caliber.RequirementDescription;
import com.starbase.caliber.RequirementTree;
import com.starbase.caliber.RequirementTreeNode;
import com.starbase.caliber.Session;
import com.starbase.caliber.Trace;
import com.starbase.caliber.TraceManager;
import com.starbase.caliber.TreeNode;
import com.starbase.caliber.attribute.UDAListValue;
import com.starbase.caliber.server.RemoteServerException;
import com.starbase.caliber.util.CaliberObjectIDUtil;

public class RequirementOperation {

    public static void main(String[] args) {
	 long logicProcessStartTime = System.nanoTime();
//	retriveNowData();
//	 analyzeRequirements();
//	 importPseudoDataForCategory();
//	 importPseudoDataForDetail();
//	 testDeleteAndSave();
	 importTraceability();
	System.out.println("Time (seconds) taken by terst is "
                 + String.valueOf((System.nanoTime() - logicProcessStartTime) / 1.0e9));
	
    }
    public static void testComparator(){
	List<String> sampleList = new ArrayList<String>();
	sampleList.add("1.11");
	sampleList.add("1.23331");
	sampleList.add("1.1");
	sampleList.add("8");
	sampleList.add("1.2");
	sampleList.add("1");
	final Comparator<String> cc = new HierarchyComparator();

	Collections.sort(sampleList, cc);
	for(String data:sampleList ){
	    System.out.println( data);
	}
    }
    public static com.starbase.caliber.Requirement  retrieveRequirement(final TreeNode n , final Session session ) throws RemoteServerException{
	com.starbase.caliber.Requirement result =null;
	final CaliberObjectID coid = n.getAssociatedObjectID();
	final CaliberObject co = session.get(coid);
	if (co!=null && co instanceof com.starbase.caliber.Requirement) {
	    result = (com.starbase.caliber.Requirement) co;
	}
	return result;
    }

    public static com.starbase.caliber.RequirementType retrieveRequirementType(final TreeNode n, final Session session) throws RemoteServerException {
	com.starbase.caliber.RequirementType result = null;
	final CaliberObjectID coid = n.getAssociatedObjectID();
	final CaliberObject co = session.get(coid);
	if (co != null && co instanceof com.starbase.caliber.RequirementType) {
	    result = (com.starbase.caliber.RequirementType) co;
	}
	return result;
    }
    private static class HierarchyComparator implements Comparator<String> {
	public int compare(String o1, String o2) {
	    final String[] array01 = StringUtils.split(o1, ".");
	    final String[] array02 = StringUtils.split(o2, ".");
	    String baseline = array01 [0];
	    String comline = array02 [0];
	    int root = baseline.compareTo(comline);
	    if(root ==0 ){
		if(array01.length==1 ){
		    return -1;
		}else if(array02.length==1){
		    return +1;
		}{
		    int baseline0 =  NumberUtils.toInt(array01[1]);
		    int comline0 = NumberUtils.toInt(array02[1]);
		   
		    return baseline0 -comline0;
		}
		 
	    }else{
		return root;
	    }
	}
    }
    public static void analyzeRequirements(){
	   File inputFile = new File("/home/weblogic/Desktop/RMcaliber");
	    final  HashMap<String,com.iisigroup.project.statistics.caliberRM.model.Requirement> hierarchyNoRequirementMapForSerial = Utils.deserialization(inputFile);
	    final Set<String> keys = hierarchyNoRequirementMapForSerial.keySet();
	    final List<String> hierarchyNo = new ArrayList<String>(keys);
	    Comparator<String> cc =new HierarchyComparator ();
	    
	    Collections.sort(hierarchyNo ,cc);
	   for(String key :  hierarchyNo){
	        com.iisigroup.project.statistics.caliberRM.model.Requirement requirement  =  hierarchyNoRequirementMapForSerial.get(key);
	       System.out.println("key: "+key+" : "+requirement.getName());
	   }
    }

    public static void importPseudoDataForCategory() {
	try {
	    final Session session = ConnectionCreator.createSession();
	    final TreeNode node = ConnectionCreator.retrieveFromProject("Address Book", "RL", session);
	    final Project project = ConnectionCreator. retrieveProject("Address Book",  session);
	    
	    File inputFile = new File("/home/weblogic/Desktop/RMcaliber");
	    final HashMap<String, com.iisigroup.project.statistics.caliberRM.model.Requirement> hierarchyNoRequirementMapForSerial = Utils
		    .deserialization(inputFile);
	    final Set<String> keys = hierarchyNoRequirementMapForSerial.keySet();
	    final List<String> hierarchyNo = new ArrayList<String>(keys);
	    Comparator<String> cc = new HierarchyComparator();
	    
	    com.starbase.caliber.RequirementType rt =   retrieveRequirementType(node, session);
	    
	    final Set<String> cateGoryNameSet = new HashSet<String>();
	    TreeNode[] childrenNodes =  node.getChildren();
	    Map<String,TreeNode> childrenNodeNameMap =new HashMap<String,TreeNode>();
	    for(final TreeNode childrenNode :childrenNodes ){
		cateGoryNameSet.add(childrenNode.getName());
		childrenNodeNameMap.put(childrenNode.getName(), childrenNode);
	    }
	    
	    Collections.sort(hierarchyNo, cc);
	    for (String key : hierarchyNo) {
		final com.iisigroup.project.statistics.caliberRM.model.Requirement requirement = hierarchyNoRequirementMapForSerial.get(key);
		final String requirementName= requirement.getName() ;
		System.out.println("key: " + key + " : " + requirement.getName());
		if (!StringUtils.contains(key, ".")  && !cateGoryNameSet.contains(requirementName)) {
		    //新增一筆category
		     com.starbase.caliber.Requirement newRequirement = new    com.starbase.caliber.Requirement(requirementName ,project ,rt,Integer.valueOf(key).intValue(),session);
		     newRequirement.save();
		} 
		
	    }	    
	} catch (RemoteServerException rse) {
	    rse.printStackTrace();
	}
    }
    public static void importPseudoDataForDetail() {
   	try {
   	    final Session session = ConnectionCreator.createSession();
   	    final TreeNode node = ConnectionCreator.retrieveFromProject("Address Book", "RL", session);
   	    final Project project = ConnectionCreator. retrieveProject("Address Book",  session);
   	    
   	    File inputFile = new File("/home/weblogic/Desktop/RMcaliber");
   	    final HashMap<String, com.iisigroup.project.statistics.caliberRM.model.Requirement> hierarchyNoRequirementMapForSerial = Utils
   		    .deserialization(inputFile);
   	    final Set<String> keys = hierarchyNoRequirementMapForSerial.keySet();
   	    final List<String> hierarchyNo = new ArrayList<String>(keys);
   	    Comparator<String> cc = new HierarchyComparator();
   	    
   	    
   	    final Set<String> cateGoryNameSet = new HashSet<String>();
   	    TreeNode[] childrenNodes =  node.getChildren();
   	    Map<String,TreeNode> childrenNodeNameMap =new HashMap<String,TreeNode>();
   	    for(final TreeNode childrenNode :childrenNodes ){
   		cateGoryNameSet.add(childrenNode.getName());
   		childrenNodeNameMap.put(childrenNode.getName(), childrenNode);
   	    }
   	    
   	    Collections.sort(hierarchyNo, cc);
   	    
   	    for (String key : hierarchyNo) {
   		final com.iisigroup.project.statistics.caliberRM.model.Requirement requirement = hierarchyNoRequirementMapForSerial.get(key);
   		final String requirementName= requirement.getName() ;
   		System.out.println("key: " + key + " : " + requirement.getName());
   		if (!StringUtils.contains(key, ".")  && !cateGoryNameSet.contains(requirementName)) {
   		    
   		}else{
   		    final  String[] stringArray = StringUtils.split(key, ".");
   		    final String categoryCode = stringArray[0];
   		    final String categoryName = CategoryEnum.getByCode(NumberUtils.toInt(categoryCode)).getValue();
   		    final TreeNode categoryNode =     childrenNodeNameMap.get(categoryName);
   		    final com.starbase.caliber.Requirement r = retrieveRequirement(categoryNode, session);
   		    com.starbase.caliber.Requirement newRequirement = new    com.starbase.caliber.Requirement(requirementName ,r,Integer.valueOf(categoryCode).intValue(),session);
   		    RequirementDescription des = new RequirementDescription(requirement.getDescription());
   		    newRequirement.setDescription(des );
   		    newRequirement.save();
   		}
   	    }
   	} catch (RemoteServerException rse) {
   	    rse.printStackTrace();
   	}
       }
    public static void importTraceability() {
   	try {
   	    final Session session = ConnectionCreator.createSession();
   	    final TreeNode node = ConnectionCreator.retrieveFromProject("Address Book", "RL", session);
   	    final Project project = ConnectionCreator. retrieveProject("Address Book",  session);
   	    
   	    File inputFile = new File("/home/weblogic/Desktop/RMcaliber");
   	    final HashMap<String, com.iisigroup.project.statistics.caliberRM.model.Requirement> hierarchyNoRequirementMapForSerial = Utils
   		    .deserialization(inputFile);
   	    final Set<String> keys = hierarchyNoRequirementMapForSerial.keySet();
   	    final List<String> hierarchyNo = new ArrayList<String>(keys);
   	    Comparator<String> cc = new HierarchyComparator();
   	    
   	    
   	    final Set<String> cateGoryNameSet = new HashSet<String>();
   	    TreeNode[] childrenNodes =  node.getChildren();
   	    Map<String,TreeNode> childrenNodeNameMap =new HashMap<String,TreeNode>();
   	    for(final TreeNode childrenNode :childrenNodes ){
   		cateGoryNameSet.add(childrenNode.getName());
   		childrenNodeNameMap.put(childrenNode.getName(), childrenNode);
   	    }
	    final TraceManager manager = (TraceManager) session.getManager(Trace.class);
	    final Map<String, Requirement> requirementNameMap = new HashMap<String, Requirement>();
	    for (final TreeNode childrenNode : childrenNodes) {
		TreeNode[] items = childrenNode.getChildren();
		for (TreeNode item : items) {
		    final Requirement r = retrieveRequirement(item, session);
		    if (r != null) {
			requirementNameMap.put(r.getName(), r);
		    }
		}
	    }
	    for (com.iisigroup.project.statistics.caliberRM.model.Requirement dataUnit : hierarchyNoRequirementMapForSerial.values()) {
		final List<String> traceFromList = dataUnit.getTraceFromList();
		final List<String> traceToList = dataUnit.getTraceToList();
		final Requirement r = requirementNameMap.get(dataUnit.getName());
		for (String traceFrom : traceFromList) {
		    final Requirement rTraceFrom = requirementNameMap.get(traceFrom);
		    if(rTraceFrom!=null){
			manager.createTrace(rTraceFrom, r, false);
		    }
		}
		for (String traceTo : traceToList) {
		    final Requirement rTraceTo = requirementNameMap.get(traceTo);
		    if(rTraceTo!=null){
			manager.createTrace(r, rTraceTo, false);
		    }
		}
	    }
   	} catch (RemoteServerException rse) {
   	    rse.printStackTrace();
   	}
       }
    public static void testDeleteAndSave(){
	try {
	    final Session session =ConnectionCreator . createSession();
	    final TreeNode node =ConnectionCreator. retrieveFromProject("Address Book", "RL", session);

	    // System.out.println(node.getRequirementTypeID().);
	    TreeNode[] childrenNodes = node.getChildren();

	    for (TreeNode n : childrenNodes) {
		System.out.println(n.getName());
		System.out.println(n.getName());
		 com.starbase.caliber.Requirement r  = retrieveRequirement(n, session);
		if (r != null) {
		    System.out.println(r.getStatus().getSelectedValue());
		    System.out.println(n.getSerialNumberTag());
		    // 新增測試
//		     com.starbase.caliber.Requirement newRequirement = new
//		     com.starbase.caliber.Requirement(n.getName()+"SDK",r,0,session);
//		     newRequirement.save();

		    // 刪除測試
		    TreeNode[] ccc = n.getChildren();
		    for (TreeNode nn : ccc) {
			CaliberObjectID aoid = nn.getAssociatedObjectID();
			CaliberObject aco = session.get(aoid);
			if (StringUtils.equals(aco.getName(), n.getName() + "SDK")) {
			    com.starbase.caliber.Requirement ar = (com.starbase.caliber.Requirement) aco;
			    ar.remove();
			}
		    }
		    
		    
		}
		
	    }

	} catch (RemoteServerException rse) {
	    rse.printStackTrace();
	}
    }
    public static void retriveNowData(){
	final ArrayList<com.iisigroup.project.statistics.caliberRM.model.Requirement> requirementList = new ArrayList<com.iisigroup.project.statistics.caliberRM.model.Requirement>();
	try {
	    final Session session =ConnectionCreator . createSession();
	    final TreeNode node =ConnectionCreator. retrieveFromProject("SRIS", "AU", session);
	    
	    final  HashMap<String,com.iisigroup.project.statistics.caliberRM.model.Requirement> hierarchyNoRequirementMapForSerial = new HashMap<String,com.iisigroup.project.statistics.caliberRM.model.Requirement>();
	    final  HashMap<String,com.starbase.caliber.Requirement> hierarchyNoRequirementMap = new HashMap<String,com.starbase.caliber.Requirement>();
	    TraverseTree(node,session,hierarchyNoRequirementMap);
	    File outFile = new File("/home/weblogic/Desktop/RMcaliber");
	    
	    final Set<String> keys = hierarchyNoRequirementMap.keySet();
	    for(String key : keys){
		
		Requirement r = hierarchyNoRequirementMap.get(key);	    
		System.out.println("name: "+r.getName());
		System.out.println("status: "+r.getStatus());
		UDAListValue aUDAListValues = r.getStatus();
		com.iisigroup.project.statistics.caliberRM.model.Requirement aRequirement = new com.iisigroup.project.statistics.caliberRM.model.Requirement();
		aRequirement.setName(r.getName());
		System.out.println("tracs from size: "+r.getTracesFrom().length);
		final Trace[] tracesFrom = r.getTracesFrom();
		for (Trace trace : tracesFrom) {
		    final CaliberObjectID coid = trace.getTraceFromID();
		    int IDNumber = coid.getIDNumber();
		    System.out.println("original IDNumber: "+IDNumber);
		    final CaliberObject co = session.get(coid);
		    if (co != null && co instanceof com.starbase.caliber.Requirement) {
			Requirement result = (com.starbase.caliber.Requirement) co;
			System.out.println(result.getName());
			aRequirement.getTraceFromList().add(result.getName());
		    }
		    //必須探索的是有辦法只靠IDNumber取得CaliberObjectID嗎 ？
		    //是靠
		    final eObjectType remoteObjType= eObjectType.REQUIREMENT_OBJECT;
		    final CaliberObjectID testCaliberObjectID = CaliberObjectIDUtil.getCaliberObjectID(remoteObjType, IDNumber);
		    int testIDNumber = testCaliberObjectID.getIDNumber();
		    System.out.println("testIDNumber: "+testIDNumber);
		}
		final Trace[] tracesTo = r.getTracesTo();
		for(Trace trace :tracesTo){
		    final CaliberObjectID coid = trace.getTraceToID();
		    int IDNumber = coid.getIDNumber();
		    System.out.println("original IDNumber: "+IDNumber);
		    final CaliberObject co = session.get(coid);
		    if (co != null && co instanceof com.starbase.caliber.Requirement) {
			Requirement result = (com.starbase.caliber.Requirement) co;
			System.out.println(result.getName());
			aRequirement.getTraceToList().add(result.getName());
		    }
		  //必須探索的是有辦法只靠IDNumber取得CaliberObjectID嗎 ？
		    //是靠
		    final eObjectType remoteObjType= eObjectType.REQUIREMENT_OBJECT;
		    final CaliberObjectID testCaliberObjectID = CaliberObjectIDUtil.getCaliberObjectID(remoteObjType, IDNumber);
		    int testIDNumber = testCaliberObjectID.getIDNumber();
		    System.out.println("testIDNumber: "+testIDNumber);
		}
		System.out.println("tracs to size: "+r.getTracesTo().length);
		aRequirement.setDescription(r.getDescription().getText());
		System.out.println("description: "+r.getDescription().getText());
		System.out.println("discussion: "+r.getDiscussion().getName());
		System.out.println("documentReference size: "+r.getDocumentReferences().length);
		requirementList.add(aRequirement);
		hierarchyNoRequirementMapForSerial.put(key, aRequirement);
	    }
	    Utils.serialization(hierarchyNoRequirementMapForSerial, outFile);

	} catch (RemoteServerException rse) {
	    rse.printStackTrace();
	}
    }
    
   
   

    public static void TraverseTree(final TreeNode parentNode, final Session session,final  Map<String,com.starbase.caliber.Requirement> data) throws RemoteServerException {
	// Print relevant information about the current node.
	PrintTreeNode(parentNode);
	Requirement requirement = retrieveRequirement(parentNode, session);
	if(requirement!=null){
	    data.put(parentNode.getHierarchyNumber(), requirement);
	}
	
	// Iterate through the parent's collection of children...
	TreeNode[] children = parentNode.getChildren();
	for (int i = 0; i < children.length; i++) {
	    TraverseTree(children[i] ,session,data);
	}
    }

    private static void PrintTreeNode(TreeNode node) {
	StringBuffer sb = new StringBuffer();
	for (int i = 0; i < node.getLevel(); i++) {
	    sb.append(" ");
	}
	sb.append(node.getHierarchyNumber());
	sb.append(" ");
	sb.append(node.getName());
	sb.append(" ");
	sb.append(node.getSerialNumberTag());
	sb.append("  ");
	sb.append(node.getClass().getSimpleName());
	sb.append("  ");
	sb.append(node.getHierarchyNumber());
	System.out.println(sb);
    }
}
